/**
 * 一组树型数据的处理方法
 */
const tree = {
  /**
   * 对树型数组的每个元素执行一次给定的函数
   * @param {Array} array 树型数组
   * @param {Function} callback 处理函数, 符合查找条件时返回true
   * @param {String} child_key 树型数据的子节点键名, 默认为children
   * @returns 返回array参数
   */
  each: (array, callback, child_key = 'children', parent) => {
    array.forEach((item, index, arr) => {
      callback(item, index, arr, parent);
      if (item && item.hasOwnProperty(child_key) && Array.isArray(item[child_key])) {
        tree.each(item[child_key], callback, child_key, item);
      }
    });
    return array;
  },

  /**
   * 创建一个新的树型数组, 这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
   * @param {Array} array 树型数组
   * @param {Function} callback 处理函数, 符合查找条件时返回true
   * @param {String} child_key 树型数据的子节点键名, 默认为children
   * @returns 新的树型数组
   */
  map(array, callback, child_key = 'children', parent) {
    return array.map((item, index, arr) => {
      let o = callback(item, index, arr, parent);
      if (item && item.hasOwnProperty(child_key) && Array.isArray(item[child_key])) {
        o[child_key] = tree.map(item[child_key], callback, child_key, item);
      }
      return o;
    });
  },

  /**
   * 查找符合条件的元素
   * @param {Array} array 树型数组
   * @param {Function} callback 处理函数, 符合查找条件时返回true
   * @param {String} child_key 树型数据的子节点键名, 默认为children
   * @returns 找到的第一个元素的值, 找不到返回undefined
   */
  find(array, callback, child_key = 'children', parent) {
    let found = undefined;
    array.some((item, index, arr) => {
      if (callback(item, index, arr, parent)) {
        found = item;
        return true;
      }
      if (item && item.hasOwnProperty(child_key) && Array.isArray(item[child_key])) {
        found = tree.find(item[child_key], callback, child_key, item);
        if (found !== undefined) return true;
      }
      return false;
    });
    return found;
  },

  /**
   * 移除符合条件的元素
   * @param {Array} array 树型数组
   * @param {Function} callback 处理函数, 符合移除条件时返回true
   * @param {String} child_key 树型数据的子节点键名, 默认为children
   * @returns 返回array参数
   */
  remove(array, callback, child_key = 'children', parent) {
    for (let index = 0; index < array.length; index++) {
      const item = array[index];
      if (callback(item, index, array, parent)) {
        array.splice(index, 1);
      } else {
        if (item && item.hasOwnProperty(child_key) && Array.isArray(item[child_key])) {
          tree.remove(item[child_key], callback, child_key, item);
        }
      }
    }
    return array;
  },

  /**
   * 树型数组转为一维数组, 会丢失树型结构
   * @param {Array} array 树型数组
   * @param {String} child_key 树型数据的子节点键名, 默认为children
   * @returns 所有元素组成的一维数组
   */
  list(array, child_key = 'children') {
    let list = [];
    array.forEach(item => {
      list.push(item);
      if (item && item.hasOwnProperty(child_key) && Array.isArray(item[child_key])) {
        list.push.apply(list, tree.list(item[child_key], child_key));
      }
    });
    return list;
  },
};

export default tree;